package com.ebupt.migu.music.schedule.service.impl;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ebupt.migu.common.util.DateUtil;
import com.ebupt.migu.common.util.HttpUtilsSMS;
import com.ebupt.migu.common.util.RedisLock;
import com.ebupt.migu.common.util.StrategyConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;

import com.ebupt.migu.common.pojo.ErrorReport;
import com.ebupt.migu.common.pojo.UserGroupStatus;
import com.ebupt.migu.music.commons.sms.Sender;
import com.ebupt.migu.music.commons.utils.FileRecordAsync;
import com.ebupt.migu.music.commons.utils.SCPAsync;
import com.ebupt.migu.music.schedule.entity.SendMessageEntity;
import com.ebupt.migu.music.schedule.entity.StatisticsSms;
import com.ebupt.migu.music.schedule.mapper.SMSTaskMapper;
import com.ebupt.migu.music.schedule.mapper.StatisticsSMSMapper;
import com.ebupt.migu.music.schedule.service.SMSTaskService;
import com.ebupt.migu.restapi.DownloadByFtp;
import com.ebupt.migu.restapi.GroupDetailDel;
import com.ebupt.migu.restapi.IopMatchPost;
import com.google.common.collect.Maps;

import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import lombok.extern.slf4j.Slf4j;

/**
 * Created by Intellij IDEA. User: liuyangyang@cd.ebupt.com Date: 2019/10/29
 */
@Slf4j
@Service
public class SMSTaskServiceImpl implements SMSTaskService {

    @Autowired
    private SMSTaskMapper smsTaskMapper;
    @Autowired
    private StatisticsSMSMapper statisticsSMSMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private FileRecordAsync fileRecordAsync;
    @Autowired
    private Sender sender;
    @Autowired
    private SCPAsync scpAsync;
    @Value("${message.send_url}")
    private String SEND_MESSAGE_URL;
    @Value("${label.post_url}")
    private String postUrl;
    @Value("${local.path}")
    private String LOCAL_PATH;

    @Value("${local.msisdn-size}")
    private String MSISDN_SIZE;

    /**
     * 正则：匹配"$xxx$"形式的字符串
     */
    private static Pattern pattern = Pattern.compile("\\$(.*?)\\$");

    /**
     * 提取默认用户名方法中使用的正则
     */
    private static Pattern default_user_name_pattern = Pattern.compile("(\\$[a-zA-Z]+)");

    /**
     * 用户信息
     */
    private final String _REDIS_KEY = "_user_info";

    /**
     * 短信策略： 立即发送短信
     */
    @Override
    public void sendMessageNow() {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        // 当前时间
        String now = simpleDateFormat.format(date);
        log.info("当前时间:{}", now);
        // 查询需要立即发送的短信策略列表
        List<HashMap<String, Object>> strategies = smsTaskMapper.querySendMessageNow();
        log.info("需要立即发送短信的策略共有:{}条", strategies.size());
        if (null == strategies || strategies.isEmpty()) {
            log.info("当前不存在需要立即发送的短信策略");
            return;
        }
        Map<String, Object> strategy = strategies.get(0);
        String strategyId = strategy.get("strategyId").toString();
        Map<String, Object> map = new HashMap<>();
        // 根据策略关联人群状态判断是否执行下发操作
        if (isSend(strategy, now)) {
            RedisLock redisLock = new RedisLock(redisTemplate, strategyId);
            if (!redisLock.getLock()) {
                log.info("{}已在其他调度中开始下发，本机终止运营", strategyId);
                return;
            }
            log.info("执行策略Id:{},执行策略名称:{}", strategyId, strategy.get("strategyName").toString());
            // 流程
            pro(strategyId, strategy, map);
            // 生成效果统计
            statistics(strategy, now);
        } else {
            log.info("未执行的策略Id:{},名称:{},人群状态异常", strategyId, strategy.get("strategyName").toString());
        }
        strategy_complete(map, strategyId);
    }

    /**
     * 短信策略： 单次发送短信
     */
    @Override
    public void sendMessageOnce() {
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        // 当前时间
        String now = simpleDateFormat.format(date);
        // 查询需要立即发送的短信策略列表
        List<HashMap<String, Object>> strategies = smsTaskMapper.querySendMessageOnce(now);
        if (null == strategies || strategies.isEmpty()) {
            log.info("当前不存在单次发送短信的策略");
            return;
        }
        Map<String, Object> strategy = strategies.get(0);
        // 获取策略ID更新相应状态
        String strategyId = strategy.get("strategyId").toString();
        Map<String, Object> map = new HashMap<>();
        // 根据策略关联人群状态判断是否执行下发操作
        if (isSend(strategy, now)) {
            RedisLock redisLock = new RedisLock(redisTemplate, strategyId);
            if (!redisLock.getLock()) {
                log.info("{}已在其他调度中开始下发，本机终止运营", strategyId);
                return;
            }
            log.info("执行策略Id:{},执行策略名称:{}", strategyId, strategy.get("strategyName").toString());
            // 流程
            pro(strategyId, strategy, map);
            // 生成效果统计
            statistics(strategy, now);
        } else {
            log.info("未执行的策略Id:{},名称:{},人群状态异常", strategyId, strategy.get("strategyName").toString());
        }
        strategy_complete(map, strategyId);
    }

    /**
     * 短信策略： 循环发送短信
     */
    @Override
    public void sendMessageLoop() throws ParseException {
        Date date = new Date();
        // 年月日时分秒
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        // 年月日
        SimpleDateFormat simpleDateFormat_day = new SimpleDateFormat(DateUtil.DATE_FORMAT_YYYY_MM_DD);
        // 时分秒
        SimpleDateFormat simpleDateFormat_time = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_HH_MI_SS);
        // 当前年月日时分秒
        String dayTime = simpleDateFormat.format(date);
        // 当前年月日
        String dayOnly = simpleDateFormat_day.format(date);
        // 当前时分秒
        String timeOnly = simpleDateFormat_time.format(date);

        // 查询需要循环发送短信的策略列表
        List<HashMap<String, Object>> strategies = smsTaskMapper.querySendMessageLoop(dayOnly);
        if (null == strategies || strategies.isEmpty()) {
            log.info("当前不存在循环发送短信的策略");
            return;
        }
        Map<String, Object> strategy = new HashMap<>();
        for (Map<String, Object> s : strategies) {
            String startTime = s.get("startTime").toString();
            String[] starts = startTime.split(" ");
            String start = starts[1];
            // 最近一次执行时间为空且执行时间小于当前时间
            if (s.get("executeTime") == null
                    && (simpleDateFormat_time.parse(start).getTime() <= simpleDateFormat_time.parse(timeOnly).getTime())) {
                strategy = s;
                break;
            }
            String executeTime = s.get("executeTime").toString();
            String[] executes = executeTime.split(" ");
            String execute = executes[0];
            // 最近一次执行时间不为空且最后一次执行日期小于今天且执行时间小于当前时间
            if ((simpleDateFormat_day.parse(execute).getTime() < simpleDateFormat_day.parse(dayOnly).getTime())
                    && (simpleDateFormat_time.parse(start).getTime() <= simpleDateFormat_time.parse(timeOnly).getTime())) {
                strategy = s;
                break;
            }
        }

        if (null == strategy.get("strategyName")) {
            log.info("当前不存在循环发送短信的策略");
            return;
        }
        // 获取策略ID更新相应状态
        String strategyId = strategy.get("strategyId").toString();
        Map<String, Object> map = new HashMap<>();
        // 根据策略关联人群状态判断是否执行下发操作
        if (isSend(strategy, dayTime)) {
            RedisLock redisLock = new RedisLock(redisTemplate, strategyId);
            if (!redisLock.getLock()) {
                log.info("{}已在其他调度中开始下发，本机终止运营", strategyId);
                return;
            }
            log.info("执行策略Id:{},执行策略名称:{}", strategyId, strategy.get("strategyName").toString());
            // 流程
            pro(strategyId, strategy, map);
            // 生成效果统计
            statistics(strategy, dayTime);
        } else {
            log.info("未执行的策略Id:{},名称:{},人群状态异常", strategyId, strategy.get("strategyName").toString());
        }
        // 策略截止日期
        String endTime = strategy.get("endTime").toString();
        map.clear();
        map.put("strategyId", strategyId);
        map.put("executing", 1);
        // 截止日期是今天，将策略状态修改成已完成。 不是今天保留进行中
        String[] ends = endTime.split(" ");
        String end = ends[0];
        if (end.equals(dayOnly)) {
            map.put("executeStatus", StrategyConstants.EXECUTE_ENDED);
            log.info("将策略状态修改为已完成");
        }
        smsTaskMapper.updateStrategyStatus(map);
    }

    /**
     * 短信策略： 间隔发送短信
     *
     * @throws ParseException
     */
    @Override
    public void sendMessageInterval() throws ParseException {
        Date date = new Date();
        // 年月日时分秒
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        // 年月日
        SimpleDateFormat simpleDateFormat_day = new SimpleDateFormat(DateUtil.DATE_FORMAT_YYYY_MM_DD);
        // 时分秒
        SimpleDateFormat simpleDateFormat_time = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_HH_MI_SS);
        // 当前年月日时分秒
        String dayTime = simpleDateFormat.format(date);
        // 当前年月日
        String dayOnly = simpleDateFormat_day.format(date);
        // 当前时分秒
        String timeOnly = simpleDateFormat_time.format(date);

        // 查询需要循环发送短信的策略列表
        List<HashMap<String, Object>> strategies = smsTaskMapper.querySendMessageInterval(dayOnly);
        if (null == strategies || strategies.isEmpty()) {
            log.info("当前不存在间隔发送短信的策略");
            return;
        }
        Map<String, Object> strategy = new HashMap<>();
        for (Map<String, Object> s : strategies) {
            String startTime = s.get("startTime").toString();
            String[] starts = startTime.split(" ");
            String start = starts[1];
            // 间隔时间
            int intervalDays = Integer.parseInt(s.get("intervalDays").toString()) + 1;
            // 最近一次执行时间为空且执行时间小于当前时间
            if (s.get("executeTime") == null
                    && (simpleDateFormat_time.parse(start).getTime() <= simpleDateFormat_time.parse(timeOnly).getTime())) {
                strategy = s;
                break;
            }
            String executeTime = s.get("executeTime").toString();
            String[] executes = executeTime.split(" ");
            String execute = executes[0];
            // 最近一次执行时间不为空且最后一次执行日期小于今天且执行时间小于当前时间
            if ((simpleDateFormat_day.parse(execute).getTime()
                    + intervalDays * 24 * 60 * 60 * 1000 == simpleDateFormat_day.parse(dayOnly).getTime())
                    && (simpleDateFormat_time.parse(start).getTime() <= simpleDateFormat_time.parse(timeOnly).getTime())) {
                strategy = s;
                break;
            }
        }

        if (null == strategy.get("strategyName")) {
            log.info("当前不存在循环发送短信的策略");
            return;
        }
        // 获取策略ID更新相应状态
        String strategyId = strategy.get("strategyId").toString();
        Map<String, Object> map = new HashMap<>();
        // 根据策略关联人群状态判断是否执行下发操作
        if (isSend(strategy, dayTime)) {
            RedisLock redisLock = new RedisLock(redisTemplate, strategyId);
            if (!redisLock.getLock()) {
                log.info("{}已在其他调度中开始下发，本机终止运营", strategyId);
                return;
            }
            log.info("执行策略Id:{},执行策略名称:{}", strategyId, strategy.get("strategyName").toString());
            // 流程
            pro(strategyId, strategy, map);
            // 生成效果统计
            statistics(strategy, dayTime);
        } else {
            log.info("未执行的策略Id:{},名称:{},人群状态异常", strategyId, strategy.get("strategyName").toString());
        }
        // 策略截止日期
        String endTime = strategy.get("endTime").toString();
        map.clear();
        map.put("strategyId", strategyId);
        map.put("executing", 1);
        // 截止日期是今天，将策略状态修改成已完成。 或下一次执行时间超出截止时间，将策略状态修改为已完成
        int intervalDays = Integer.parseInt(strategy.get("intervalDays").toString()) + 1;
        String[] ends = endTime.split(" ");
        String end = ends[0];
        if ((simpleDateFormat_day.parse(dayOnly).getTime() + intervalDays * 24 * 60 * 60 * 1000 > simpleDateFormat_day
                .parse(end).getTime()) || (end.equals(dayOnly))) {
            map.put("executeStatus", StrategyConstants.EXECUTE_ENDED);
            log.info("将策略状态修改为已完成");
        }
        smsTaskMapper.updateStrategyStatus(map);
    }

    /**
     * 根据策略关联人群状态判断是否执行下发操作
     *
     * @param strategy
     * @param time
     * @return
     */
    private boolean isSend(Map<String, Object> strategy, String time) {
        boolean isSend;
        String strategyId = strategy.get("strategyId").toString();
        String groupId = strategy.get("groupId").toString();
        String status = smsTaskMapper.qryUserGroupStatus(groupId);
        Map<String, Object> map = new HashMap<>();
        map.put("strategyId", strategyId);
        map.put("executeTime", time);
        if (UserGroupStatus.FINISH.getVal().equals(status)) {
            map.put("executeStatus", StrategyConstants.EXECUTE_ONGOING);
            map.put("executing", 2);
            isSend = true;
        } else {
            // 人群不是已完成状态，不能发送，记录下发失败日志
            ErrorReport errorReport = new ErrorReport();
            errorReport.setGid(groupId).setSid(strategyId).setCreateTime(time)
                    .setRemark(UserGroupStatus.getMsg(status));
            smsTaskMapper.insertErrorReport(errorReport);
            isSend = false;
        }
        // 更新
        smsTaskMapper.updateStrategyStatus(map);
        return isSend;
    }

    /**
     * 提取{}中的参数并以数组形式返回
     *
     * @param str
     * @return
     */
    private String[] getParams(String str) {
        List<String> params = new ArrayList<>();
        // 提取{}中的参数
        Pattern pattern = Pattern.compile("(?<=\\{)[^\\}]+");
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            params.add(matcher.group());
        }
        // 提取不到参数
        if (null == params || params.size() == 0) {
            return null;
        }
        // 生成String[]
        String[] tplVars = new String[params.size()];
        for (int i = 0; i < params.size(); i++) {
            tplVars[i] = params.get(i);
        }
        log.info("提取到大括号中的参数:{}", tplVars.toString());
        return tplVars;
    }

    /**
     * 短信效果统计
     *
     * @param strategy
     * @param start
     */
    private void statistics(Map<String, Object> strategy, String start) {
        StatisticsSms statisticsSms = new StatisticsSms();
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        // 策略结束时间
        String end = simpleDateFormat.format(date);
        // 策略ID、策略名称、人群ID、人群名称
        String strategy_id = strategy.get("strategyId").toString();
        String strategy_name = strategy.get("strategyName").toString();
        String group_id = strategy.get("groupId").toString();
        String group_name = strategy.get("groupName").toString();
        String create_time = strategy.get("createTime").toString();
        // 查询人群规模
        Integer size = smsTaskMapper.size(group_id);
        // 效果统计内容
        statisticsSms.setStrategyId(strategy_id);
        statisticsSms.setStrategyName(strategy_name);
        statisticsSms.setGroupId(group_id);
        statisticsSms.setGroupName(group_name);
        statisticsSms.setGroupSize(size);
        statisticsSms.setSuccess(0);
        statisticsSms.setFail(0);
        statisticsSms.setStartTime(start);
        statisticsSms.setEndTime(end);
        statisticsSms.setCreateTime(create_time);
        statisticsSms.setDate(DateUtil.getDateToday());
        log.info("sms statistics info: {}", statisticsSms.toString());
        // 生成效果统计记录
        statisticsSMSMapper.insert(statisticsSms);
    }

    /**
     * 策略完成
     *
     * @param map
     * @param sid
     */
    private void strategy_complete(Map<String, Object> map, String sid) {
        map.clear();
        map.put("strategyId", sid);
        map.put("executing", 1);
        map.put("executeStatus", StrategyConstants.EXECUTE_ENDED);
        log.info("将策略状态修改为已完成");
        smsTaskMapper.updateStrategyStatus(map);
    }

    /**
     * 原子自增
     *
     * @return
     */
    private void redis_incr(String key_name) {
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key_name, redisTemplate.getConnectionFactory());
        redisAtomicLong.getAndIncrement();
    }

    /**
     * 删除key
     *
     * @param key_name
     */
    private void redis_remove(String key_name) {
        redisTemplate.delete(key_name);
    }

    /**
     * 剔除黑名单用户
     */
    private List<String> removeBlackList(String[] ids) {
        List<String> members = new ArrayList<>();
        for (String id : ids) {
            List<String> blacks = smsTaskMapper.queryRosterMembers(id);
            if (null != blacks && !blacks.isEmpty()) {
                members.addAll(blacks);
            }
        }
        return members;
    }

    /**
     * 添加白名单用户
     */
    private List<String> addWhiteList(String[] ids) {
        List<String> members = new ArrayList<>();
        for (String id : ids) {
            List<String> whites = smsTaskMapper.queryRosterMembers(id);
            if (null != whites && !whites.isEmpty()) {
                members.addAll(whites);
            }
        }
        return members;
    }

    /**
     * 核心流程
     *
     * @param strategyId
     * @param strategy
     * @param map
     */
    private void pro(String strategyId, Map<String, Object> strategy, Map<String, Object> map) {
        // 白名单成员
        List<String> whites = new ArrayList<>();
        // 黑名单成员
        List<String> blacks = new ArrayList<>();
        // 白名单： 1-添加白名单
        String[] white = null;
        // 黑名单： 1-剔除黑名单
        String[] black = null;
        // 是否进入方舟逻辑发送
        boolean isMrkgroup = false;
        // 若是合并客群，将合并的那些方舟客群保存在这里
        List<Map> arkGroupList = null;
        if (null != strategy.get("white")) {
            // 多选白名单
            white = String.valueOf(strategy.get("white")).split(",");
        }
        if (null != strategy.get("black")) {
            // 多选黑名单
            black = String.valueOf(strategy.get("black")).split(",");
        }
        // 添加白名单用户
        if (white != null && white.length > 0) {
            log.info("添加白名单用户");
            whites = addWhiteList(white);
        }
        // 剔除黑名单用户
        if (black != null && black.length > 0) {
            log.info("剔除黑名单用户");
            blacks = removeBlackList(black);
        }
        // 短信内容
        String content = String.valueOf(strategy.get("smsContent"));
        log.info("短信内容:{}", content);
        // 默认用户名
        String smsDefaultUsername = defaultUserName(content);
        log.info("默认用户名：{}", smsDefaultUsername);
        // 短信模板ID
        String templateId = strategy.get("templateId").toString();
        log.info("模板ID:{}", templateId);
        // bound: 统一处理当前key
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(_REDIS_KEY);
        // 用户群ID
        String groupId = strategy.get("groupId").toString();
        log.info("group id: {}", groupId);
        // 策略名称
        String strategyName = (String) strategy.get("strategyName");
        // 客群创建方式
        String groupCreateWay = smsTaskMapper.queryUserGroupCreateWay(groupId);
        // 发送名单存档
        // fileRecordAsync.record(strategyId, groupId, whites, blacks);
        String recordFile = create_sftp_data_sync_record(groupId, strategyId);
        // 判断是否是合并客群，且合并的客群中有方舟同步客群
        arkGroupList = getArkGroupList(groupId);
        if (arkGroupList != null && arkGroupList.size() > 0) {
            isMrkgroup = true;
        }
        String dateTime = DateUtil.getDateToday();
        // 创建号码明细表
        if (isMrkgroup || groupCreateWay.equals(StrategyConstants.ARK_IMPORT_GROUP)) {
            smsTaskMapper.createSmsInfoTable(dateTime);
            strategy.put("dateToday", DateUtil.getDateToday());
        }
        // 创建流失策略明细表
        if (strategyName.contains("流失")) {
            smsTaskMapper.createliushiInfoTable(DateUtil.getThuDate());
            strategy.put("dateToday", DateUtil.getDateToday());
            if (strategy.get("jobType").toString().equals("1") || strategy.get("jobType").toString().equals("2")) {
                strategy.put("liushiStartTime", strategy.get("executeTime"));
            } else {
                strategy.put("liushiStartTime", strategy.get("startTime"));
            }
        }
        if (redisTemplate.hasKey(groupId + "-phone")) {
            // 默认为redis取人群数据
            if (redisTemplate.opsForSet().size(groupId + "-phone").intValue() <= 0) {
                log.info("目标人群不存在，无法进行短信发送,向人群创建人和修为人发送消息");
                HttpUtilsSMS.doPost(SEND_MESSAGE_URL, new SendMessageEntity("1", "1", null, groupId));
                HttpUtilsSMS.doPost(SEND_MESSAGE_URL, new SendMessageEntity("2", "1", null, groupId));
                // 将策略状态修改为已完成
                strategy_complete(map, strategyId);
                return;
            }
            Cursor<String> cursor = redisTemplate.opsForSet().scan(groupId + "-phone", ScanOptions.NONE);
            int i = 0;
            while (cursor.hasNext()) {
                String msisdn = cursor.next();
                if (blacks.contains(msisdn)) {
                    continue;
                }
                if (whites.contains(msisdn)) {
                    continue;
                }
                // TODO 20241015 将短信改成200条一次批量下发
                List<String> msisdns = new ArrayList<>();
                if (!matcher(content)) {
                    while (cursor.hasNext() && msisdns.size() < Integer.parseInt(MSISDN_SIZE)) {
                        msisdns.add(cursor.next());
                    }
                    StringBuilder sb = new StringBuilder(msisdn);
                    msisdns.remove(msisdn);
                    msisdns.forEach(m -> {
                        sb.append(",");
                        sb.append(m);
                    });
                    msisdn = sb.toString();
                }
                log.info("包含用户数：{}", msisdn.split(",").length);
                i = i + msisdn.split(",").length;
                // 替换用户名
                content = replaceName(content, msisdn, smsDefaultUsername, boundHashOperations);
                // 发送短信
                if (groupCreateWay.equals(StrategyConstants.ARK_IMPORT_GROUP)) {
                    if (!strategy.containsKey("buriedType")) {
                        strategy.put("buriedType", "1");
                    }
                    chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                            strategy);
                } else if (isMrkgroup) {// 埋点合并方舟客群的情况
                    Map group = isBlongArkUserGroup(arkGroupList, msisdn);
                    if (group == null) {
                        chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                                strategy);
                    } else {
                        // 修改变量strategy中的参数，于是复制新的
                        Map<String, Object> copyStrategy = Maps.newHashMap();
                        copyStrategy.putAll(strategy);
                        copyStrategy.put("groupId", group.get("groupId"));
                        copyStrategy.put("groupName", group.get("groupName"));
                        copyStrategy.put("buriedType", "1");
                        chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                                copyStrategy);
                    }
                } else if (strategyName.contains("流失")) {
                    if (!strategy.containsKey("buriedType")) {
                        strategy.put("buriedType", "2");
                    }
                    chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                            strategy);
                } else {
                    chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                            strategy);
                }
            }
            log.info("总计下发：{}", i);
            // 处理白名单
            if (whites.size() != 0) {
                for (String msisdn : whites) {
                    log.info("向白名单成员{}发送短信", msisdn);
                    // 替换用户名
                    content = replaceName(content, msisdn, smsDefaultUsername, boundHashOperations);
                    chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                            strategy);
                }
            }
        } else {
            // 判断用户群是否属于标签服务平台
            HashMap<String, Object> labelUserGroup = smsTaskMapper.isLabelUserGroup(groupId);
            if (null != labelUserGroup && labelUserGroup.size() > 0) {
                // 对接标签服务平台取人群
                File file = DownloadByFtp.getLabelUserGroup(strategy, postUrl, 1);
                if (null == file || file.length() == 0) {
                    log.info("目标人群不存在，无法进行短信发送,向人群创建人和修为人发送消息");
                    HttpUtilsSMS.doPost(SEND_MESSAGE_URL, new SendMessageEntity("1", "1", null, groupId));
                    HttpUtilsSMS.doPost(SEND_MESSAGE_URL, new SendMessageEntity("2", "1", null, groupId));
                    // 将策略状态修改为已完成
                    strategy_complete(map, strategyId);
                    return;
                }
                String msisdn;
                try {
                    // 下发明细记录
                    BufferedWriter writer = new FileWriter(recordFile).getWriter(true);
                    BufferedReader reader = new FileReader(file).getReader();
                    int i = 0;
                    while ((msisdn = reader.readLine()) != null) {
                        if (!"".equals(msisdn)) {
                            if (blacks.contains(msisdn)) {
                                continue;
                            }
                            if (whites.contains(msisdn)) {
                                continue;
                            }
                            log.info("当前向手机号{}发送短信", msisdn);
                            // TODO 20241015 将短信改成200条一次批量下发
                            List<String> msisdns = new ArrayList<>();
                            if (!matcher(content)) {
                                boolean flag = false;
                                while (!flag && msisdns.size() < Integer.parseInt(MSISDN_SIZE)) {
                                    String tel = reader.readLine();
                                    if (null != tel && !"".equals(tel)) {
                                        msisdns.add(tel);
                                    } else {
                                        flag = true;
                                    }
                                }
                                StringBuilder sb = new StringBuilder(msisdn);
                                msisdns.remove(msisdn);
                                msisdns.forEach(m -> {
                                    sb.append(",");
                                    sb.append(m);
                                });
                                msisdn = sb.toString();
                            }
                            log.info("包含用户数：{}", msisdn.split(",").length);
                            i = i + msisdn.split(",").length;
                            // 替换用户名
                            content = replaceName(content, msisdn, smsDefaultUsername, boundHashOperations);
                            if (strategyName.contains("流失")) {
                                if (!strategy.containsKey("buriedType")) {
                                    strategy.put("buriedType", "2");
                                }
                                chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn,
                                        content, strategy);
                            } else if (isMrkgroup) {
                                // 埋点合并方舟客群的情况
                                Map group = isBlongArkUserGroup(arkGroupList, msisdn);
                                if (group == null) {
                                    chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn,
                                            content, strategy);
                                } else {
                                    Map<String, Object> copyStrategy = Maps.newHashMap();
                                    copyStrategy.putAll(strategy);
                                    copyStrategy.put("groupId", group.get("groupId"));
                                    copyStrategy.put("groupName", group.get("groupName"));
                                    copyStrategy.put("buriedType", "1");
                                    chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn,
                                            content, copyStrategy);
                                }
                            } else {
                                chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn,
                                        content, strategy);
                            }
                            writer.write(msisdn + "|^|" + strategyId);
                            writer.newLine();
                        }
                    }
                    reader.close();
                    // 处理白名单
                    if (whites.size() != 0) {
                        for (String phone : whites) {
                            log.info("向白名单成员{}发送短信", phone);
                            // 替换用户名
                            content = replaceName(content, phone, smsDefaultUsername, boundHashOperations);
                            chooseSendWay(strategy.get("useWaySendSms").toString(), strategyId, templateId, msisdn, content,
                                    strategy);
                            writer.write(phone + "|^|" + strategyId);
                            writer.newLine();
                        }
                    }
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // 对接标签平台客群销毁通知
                if (file.delete()) {
                    GroupDetailDel.del(strategy);
                }
            }
        }
    }

    /**
     * 替换短信内容
     *
     * @param content     短信内容
     * @param msisdn      手机号码
     * @param defaultName 默认用户名
     * @return
     */
    private String replaceName(String content, String msisdn, String defaultName,
                               BoundHashOperations boundHashOperations) {
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            String userName = defaultName;
            if (boundHashOperations.hasKey(msisdn)) {
                userName = String.valueOf(boundHashOperations.get(msisdn));
            }
            content = content.replace(matcher.group(), userName);
        }
        return content;
    }

    private boolean matcher(String content) {
        Matcher matcher = pattern.matcher(content);
        return matcher.find();
    }

    /**
     * 提取默认用户名
     *
     * @param context
     * @return
     */
    private String defaultUserName(String context) {
        String name = "";
        Matcher matcher = default_user_name_pattern.matcher(context);
        if (matcher.find()) {
            // 获取匹配key userName
            String key = matcher.group().substring(1);
            // 获取要替换的文本内容 $userName:白金会员$
            String str =
                    context.substring(context.indexOf("$", matcher.start()), context.indexOf("$", matcher.end()) + 1);
            // 获取默认的值 白金会员
            String defaultVal = str.substring(str.indexOf(":") + 1, str.length() - 1);
            name = defaultVal;
        }
        return name;
    }

    /**
     * 新增sftp文件同步记录
     *
     * @param groupId
     * @param strategyId
     */
    private String create_sftp_data_sync_record(String groupId, String strategyId) {
        Map<String, Object> map = new HashMap<>();
        map.put("groupId", groupId);
        map.put("strategyId", strategyId);
        map.put("localPath", LOCAL_PATH);
        map.put("fileName", "a_10008_80028_" + DateUtil.getDateToday() + "_" + strategyId + ".dat");
        smsTaskMapper.create_sftp_data_sync_record(map);
        return map.get("localPath").toString() + map.get("fileName").toString();
    }

    private Map isBlongArkUserGroup(List<Map> arkGroupList, String phone) {
        for (Map group : arkGroupList) {
            if (redisTemplate.opsForSet().isMember(group.get("groupId") + "-phone", phone)) {
                return group;
            }
        }
        return null;
    }

    private List<Map> getArkGroupList(String groupId) {
        String resGroups = smsTaskMapper.getUserGroupResgroup(groupId);
        if (StringUtils.isNotBlank(resGroups)) {
            List<String> resGroup = Arrays.asList(resGroups.split(","));
            return smsTaskMapper.isArkUserGroup(resGroup);
        }
        return null;
    }

    private void chooseSendWay(String sendWay, String strategyId, String templateId, String msisdn, String content,
                               Map<String, Object> strategy) {
        // iop标签验证
        boolean match = true;
        if (StringUtils.isNotEmpty(strategy.get("iopTagId").toString())) {
            IopMatchPost ip = new IopMatchPost();
            match = ip.iopMatch(strategy.get("iopTagId").toString(), strategyId, msisdn);
            if (match) {
                redis_incr(strategyId + "_" + DateUtil.getDateToday() + "_iop");
            }
        }
        if (match) {
            if (sendWay.equals("0")) {
                // 旧的短信下发方式
                // 提取参数
                String[] params = getParams(content);
                sender.sendSMS(strategyId, templateId, new String[]{msisdn}, params, strategy);
            } else {
                // 大营销平台下发方式
                sender.send2MegamarketSMS(strategyId, msisdn, content, strategy);
            }
        }
    }

    @Override
    public String testSendMegamarket(Map<String, Object> map) {
        List<String> phoneList = (List<String>) map.get("phoneList");
        String sid = (String) map.get("sid");
        String content = "这个是测试短信，用于测试大营销平台短信下发";
        for (String s : phoneList) {
            sender.testsend2MegamarketSMS(sid, s, content);
        }
        return "success";
    }
}